import common from "../../../utils/common"
const db = wx.cloud.database()
let audio = wx.createInnerAudioContext({
    useWebAudioImplement: true
})
let m = 0, // 单词起始位置
    n = 5, // 默认学习条数，初始值为5
    array = [], //存放单词数据
    idx = 0, //单词初始下标，默认0
    optionsNum = 0,
    today = new Date(), // 对已学单词加入年月日
    year = today.getFullYear(),
    mon = today.getMonth() + 1,
    day = today.getDate(),
    // 两个单词本以学的数量，通过缓存判断当前单词本，点击next加一，接着存入缓存中
    a = 0,
    rvw_arr = [],
    newArr = {},
    today_cnt = 0,
    time = '',
    autoPlay = wx.getStorageSync('autoplay'),
    movableTmpX = 0,
    movableTmpY = 0,
    movableChangeFlag = false, // 是否移动
    delList = [],
    cptword = {},
    lineData = {};

Page({

    /**
     * 页面的初始数据
     * 初始单词下标从0开始，onload加载第一组数据，并渲染下标0的数据
     * 点击下一个，下标首先+1，如果此时下标值超过数据长度（含等于），弹出提示。不超过就渲染新的数据。
     * 对于弹框提示中，用户选择继续，当下标归为0，数据长度也为新数据长度，并渲染一次数据。
     */

    data: {
        lyricShow: false,
        showNot: true,
        showDef: false,
        definition: "",
        popShowNot: true,
        starNot: true,
        is_play: false,
        delNot: true,
        x: 0,
        y: 0,
        searchShow: false,
        viewportInfo: null, // 视口样式信息
        movableAreaInfo: null, // movableArea 样式信息
        movableViewInfo: null, // movableView 样式信息
        movableViewAnimation: false // movableView 动画是否开启
    },

    getDef: function () { // 释义显示
        this.setData({
            showDef: !this.data.showDef
        })
    },

    clickShow: function () { // 歌词显示
        this.setData({
            lyricShow: !this.data.lyricShow
        })
    },

    async showPopup(e) {
        // this.cptstopAudio()
        console.log(e.detail.value)
        audio.stop()
        let {
            inputText
        } = this.data
        inputText = e.detail.value
        if (inputText) {
            await common.qureyWordAuido(this, inputText)
            this.clearInput()
        }

        cptword = await wx.getStorageSync('queryWord')
        console.log(cptword)

    },

    cptstopAudio() { // 暂停播放
        common.cptstopAudio()
    },

    playAudioBySentence() {
        common.playAudioBySentence(cptword.address)
    },

    /**
     * 清空输入框
     */
    clearInput() {
        this.setData({
            inputText: '',
            searchShow: false
        })
    },

    onReady: function () {
        this.component = this.selectComponent("#_popup")
        // 之所以写在这里，是因为毕竟是初始化样式嘛，写在 onLoad 和 onShow 里边都不能确保样式已经渲染完毕，页面已经准备完毕了，所以写在 onReady 里边初始化
        const query = wx.createSelectorQuery().in(this) // 这个 in(this) 在自定义组件内部使用相当有用，这里有没有都行
        query.selectViewport().boundingClientRect()
        query.selectAll('#movableArea,#movableView').boundingClientRect()
        query.exec(res => { // 统一获取样式
            let viewportInfo = res[0] // 这里可以获取当前屏幕视口的宽高，如果设置 movableArea 区域的话，这个相当有用，这里没用上
            let movableAreaInfo = res[1][0] // 这是获取的 movableArea 样式
            let movableViewInfo = res[1][1] // 这里获取的 movableView 样式
            let x = movableAreaInfo.width - movableViewInfo.width - 48 // 这里之所以多减了 48 ，只是作为展示动态的初始化 x,y 怎样不让 movableView 过渡过去
            let y = movableAreaInfo.height - movableViewInfo.height - 48 // 这里之所以多减了 48 ，只是作为展示动态的初始化 x,y 怎样不让 movableView 过渡过去
            this.setData({
                x,
                y,
                viewportInfo,
                movableAreaInfo,
                movableViewInfo
            })
            setTimeout(() => {
                this.setData({
                    movableViewAnimation: true // 初始化 x y 之后把动画打开，注意：一定要和上边的设置 x y 初始值区分开，不然设置初始值的时候还是会过渡过去，这个就没意义了
                })
            })
        })
    },

    // 滑动滑块 记录滑块当前的 X,Y
    movableViewChangeHandler: function ({
        detail
    }) {
        let {
            x,
            y,
            source
        } = detail
        if (source === 'touch') { // 这里是只记录手指滑动的 X Y
            movableChangeFlag = true // 代表移动过
            movableTmpX = x // 记录滑块当前的 X
            movableTmpY = y // 记录滑块当前的 Y
        }
    },

    // 手指滑动结束事件
    movableViewTouchEndHandler: function (e) {
        if (movableChangeFlag) { // 移动过才触发，不移动单纯点击不触发
            let {
                width: movableAreaWidth,
                height: movableAreaHeight
            } = this.data.movableAreaInfo
            let {
                width: movableViewWidth,
                height: movableViewHeight
            } = this.data.movableViewInfo
            let tmpX = 0,
                tmpY = movableTmpY
            // 计算当前 X 偏向于左还是右
            if (movableTmpX + movableViewWidth / 2 > movableAreaWidth / 2) { // 如果偏向于右侧，则向右靠拢
                tmpX = movableAreaWidth - movableViewWidth // 设置 X 为最右侧
            } else { // 如果偏向于左侧，则向左靠拢
                tmpX = 0 // 设置 X 为最左侧
            }
            // 第一次设置 X,Y
            this.setData({
                x: tmpX,
                y: tmpY
            })
            // 第二次设置 X,Y ，实际上这里只需要设置 Y 就行了，因为有问题的是 Y，不过这里把 X 也设置了，防止 X 也有问题
            setTimeout(() => {
                this.setData({
                    x: tmpX,
                    y: tmpY
                })
                // 其实这里延迟不给就行，但是为了确保可行性，还是协商了 20ms 的延迟，基本上没啥感知
            }, 20)
            movableChangeFlag = false // 重置为未移动过
        }
    },

    async onLoad(options) {
        time = year + '-' + mon + '-' + day
        if (!wx.getStorageSync('punchCard') || wx.getStorageSync('punchCard').today_time !== time){
            await wx.setStorageSync('punchCard', { 
                punchCard: 'noCard',
                today_time: time
            })
        }
        lineData = wx.getStorageSync('lineData')
        // console.log('获取的数据',lineData[lineData.length-1].time,time == lineData[lineData.length-1].time)

        if (lineData.length > 0 && lineData[lineData.length - 1].time == time) {
            today_cnt = lineData[lineData.length - 1].today_cnt //获取已缓存的today_cnt
            console.log('today_cnt', today_cnt)
            today_cnt += 1
        } else {
            console.log('没走到这一步')
            today_cnt += 1
        }

        console.log('当前cnt', today_cnt)

        m = 0
        n = 5
        idx = 0 // 每次进入页面时，单词起始下标归为0，避免数据残留
        if (options.taskNum) {
            optionsNum = options.taskNum
            console.log('需要学习的数量：', options.taskNum)
            // 重置学习条数
            n = parseInt(options.taskNum)
        }
        // 必须有书籍缓存，才会进入当前页面，所以无需判断是否有缓存
        let currBook = wx.getStorageSync('currBook')
        console.log('当前book', currBook)
        this.type = currBook.type
        // 根据当前书籍的类型type，获取已学习进度
        if (currBook.type == 'cet4') {
            if (wx.getStorageSync('cet4Progress')) {
                m = wx.getStorageSync('cet4Progress')
            }
        } else if (currBook.type == 'cet6') {
            if (wx.getStorageSync('cet6Progress')) {
                m = wx.getStorageSync('cet6Progress')
            }
        } else if (currBook.type == 'kaoyan') {
            if (wx.getStorageSync('kaoyanProgress')) {
                m = wx.getStorageSync('kaoyanProgress')
            }
        }
        // 根据值传递，获取对应数据库数据，此时数据从下标m开始
        // 此时的下标是进入页面的初始下标0，即idx为0，获取数据
        // 没有学习记录，从0开始获取。有记录，在上次学习的最后一个单词数量上+1后，开始获取数据
        // 初次进入页面，此处只需直接传值，不需要改变m的值，避免影响setdata()方法中的数据处理
        array = await this.getinfo(m == 0 ? 0 : m + 1, n, currBook.type)
        console.log('array', array)
        // 渲染数据
        // 初次进入页面，发生跳数据问题。也就是m值此时不可改变
        this.setdata(m, currBook.type)
    },
    show: function () {
        console.log('word', array[idx].content)
        wx.navigateTo({
            url: "/pages/dictionary/wordDetail/wordDetail?content=" + array[idx].content + '&id=' + array[idx]._id
        })
    },

    async inputShow() {
        new Promise(() => {
            this.setData({
                searchShow: !this.data.searchShow
            })
            this.animate('.search', [{
                width: '0',
                height: "0"
            }, {
                width: "170px",
                height: '35px'
            }], 400)
        })
    },

    /**
     * 查询数据
     */
    async next(e) {
        today_cnt += 1 // 记录当前学习数量
        // 下标递增
        idx += 1

        this.setData({ //  反应掉帧
            showDef: false,
            showNot: true,
            starNot: true
        })

        // 满足打卡条件
        if ((idx+1) == optionsNum && wx.getStorageSync('punchCard').punchCard == 'noCard') { 
            wx.setStorageSync('punchCard', {
                punchCard: "canCard",
                today_time: time
            })
            await common.autoCard(time, year, mon, day)
        }

        // 有音频则播放没有则停止播放当前音频并且查询音频状态
        if (array[idx] && array[idx].address) {
            array[idx].address ? this.playmusic(array[idx].address) : this.stopAudio()
        }
        // 数据长度5，下标应从0到4，下标为5时需要弹框。即下标值idx≥数据长度n，弹框。数据长度同时也是学习的条数n
        if (idx >= n) {
            // 此时下标溢出，必须弹框
            let res = await wx.showModal({
                cancelColor: 'green',
                title: '提示',
                content: '你已经完成今日任务啦',
                cancelText: "去打卡",
                confirmText: "再来一点"
            })
            if (res.confirm) {
                // 用户确定继续，下标归0；单词新的起始位置m，为当前位置m+学习条数n，即m+=n，重置后开始获取新的数据，并赋值到array
                idx = 0
                m += n
                array = await this.getinfo(m + 1, n, this.type)
                // 渲染数据
                this.setdata(m, this.type)
                console.log('加入数组的数据为', array, idx, m, n)
            } else {
                // 用户去打卡页面
                wx.navigateTo({
                    url: '/pages/study/punchCard/punchCard?optionsNum=' + optionsNum,
                })
            }
        }
        // 下标未溢出
        else {
            // 下标值未超过学习条数时，继续渲染数据。m从0开始
            console.log('next中，m的值为：', m)
            this.setdata(m, this.type)
        }

        // 更新学习进度，分当前、新增
        let arr = wx.getStorageSync('lineData'),
            data = [],
            Tod_flag = true,
            // time = year + '-' + mon + '-' + day,

            new_data = { // 当天数据
                time,
                today_cnt
            };
        // data.push(arr)
        if (arr.length) {
            arr.forEach(item => {
                if (item.time == new_data.time) {
                    item.today_cnt = new_data.today_cnt
                    Tod_flag = false;
                }
                data.push(item);
            })
        }

        if (Tod_flag) {
            data.push(new_data);
        }
        wx.setStorageSync('lineData', data);
    },

    /**
     * 添加生词本
     */
    async addWord() {
        new Promise(() => {
            let {
                content,
                _id
            } = array[idx]
            this.setData({
                showNot: false,
            })
            common.addNoteWord(array[idx],content, _id)
        })
    },

    /**
     * 组件添加生词本
     */
    cptAddWord() {
        let {
            content,
            _id
        } = cptword
        this.setData({
            popShowNot: false,
        })
        this.addWord('', content, _id)
    },

    cptCancelWord(e, _id) {
        common.delNoteWord(cptword._id)
        this.setData({
            popShowNot: true
        })
    },

    /**
     * 取消添加的单词
     */
    async cancelWord() {
        new Promise(() => {
            let {
                _id
            } = array[idx]
            this.setData({
                showNot: true,
            })
            common.cancelStar(_id)
        })
    },

    // 单词斩
    delWord() {
        delList.push(array[idx].content)
        this.setData({
            delNot: false
        })
        console.log('delList', delList)
    },

    canDelWord() {
        delList.forEach((item, index) => {
            if (item == array[idx].content) {
                delList.splice(index, 1);
            }
        });
        this.setData({
            delNot: true
        })
    },

    read: function () {
        this.playAudioByWord(array[idx].content)
    },

    popupRead() {
        this.playAudioByWord(cptword.content)
    },

    /**
     * 根据单词，设置音频地址并播放。同时监听音频停止事件
     */
    playAudioByWord(word) {
        audio.src = `https://dict.youdao.com/dictvoice?audio=${word}&type=2`
        audio.play()
        audio.onStop(res => {
            // 清空音频链接
            audio.src = ''
        })
    },

    // 收藏单词
    async star() {
        new Promise(() => {
            let {
                content,
                _id
            } = array[idx]

            this.setData({
                starNot: false,
            })
            common.addStar(content, _id)
        })
    },

    async cancelStar() {
        new Promise(() => {
            this.setData({
                starNot: true,
            })
            common.cancelStar(array[idx]._id)
        })
    },

    /**
     * 停止音频文件
     */
    stopAudio() {
        audio.stop()
        audio.src = '' // 将地址置空
    },

    //播放
    playmusic(address) {
        const {
            is_play
        } = this.data
        if (is_play) {
            audio.pause();
            this.setData({
                is_play: false
            })
            console.log("暂停播放")
        } else if (!is_play) {
            audio.src = address
            audio.play();
            this.setData({
                is_play: true
            })
            console.log("继续播放")
        }
    },

    // 判断单词状态
    async music(e, address) {
        let currWord = array[idx]
        address ? address : currWord.address
        if (address || currWord.address) {
            this.playmusic(address || currWord.address)
        } else {
            await common.qureyAudioStatus(array[idx].content)
        }
        console.log(this.data.is_play)
    },

    // 获取数据(利用云函数来获取)
    async getinfo(m, n, type) {
        wx.showLoading({
            title: '获取中',
        })
        // 调用getDictWord云函数，并传入m,n值
        let res = await wx.cloud.callFunction({
            name: 'getDictWord',
            data: {
                m,
                n,
                type
            }
        })

        wx.hideLoading()

        new Promise(() => { // 单词加粗
            res.result.forEach(item => {
                if (item.lyric) {
                    common.processLyric(item)
                }
            });
        })
        console.log('处理后的数据：', res.result)
        return res.result
    },

    queryPlaySet(audioAddress) {
        if (audioAddress.address && autoPlay) { // 判断是否能自动播放
            console.log('autoPlay', autoPlay)
            this.playmusic(audioAddress.address)
        } else if (!audioAddress.address && autoPlay) { // 如果没此字段和自动播放设置就查询审核音频库
            this.music(" ", audioAddress.address)
            console.log('调用了music')
        }
    },

    // 渲染数据
    async setdata(m, type) {
        a = m + idx + 1
        console.log('设置数据a后', a)
        // console.log(`加载第${idx+1}个单词`)
        if (type == 'cet4') { // 加入缓存
            wx.setStorageSync('cet4Progress', a)
        } else if (type == 'cet6') {
            wx.setStorageSync('cet6Progress', a)
        } else if (type == 'kaoyan') {
            wx.setStorageSync('kaoyanProgress', a)
        }

        let content = array[idx].content
        let _id = array[idx]._id
        console.log('存入的数组：', content, _id)

        delList.includes(content) ? this.setData({
            delNot: false
        }) : this.setData({
            delNot: true
        })

        if (content) { // 学习结束添加到复习本
            rvw_arr.push({
                content,
                _id
            })
        }

        console.log('去重前的值：', rvw_arr)
        let deWeightThree = () => { // 键值对去重
            let map = new Map();
            for (let item of rvw_arr) {
                if (!map.has(item.content)) {
                    map.set(item.content, item);
                }
            }
            return [...map.values()];
        }
        newArr = deWeightThree();

        // let unique = () => { // 列表去重
        //   return Array.from(new Set(rvw_arr))
        // }
        // newArr = unique();
        this.queryPlaySet(array[idx]) // 查询播放设置

        console.log('去重后的值：', newArr)
        this.setData({
            word: array[idx]
        })
    },

    /**监听用户退出当前页面,数据库缓存数据 */
    async onUnload() { // TODO
        newArr = newArr.filter((item) => {
            return delList.indexOf(item.content) < 0
        })
        console.log(newArr)
        if (newArr.length > 0) {
            await db.collection('reviewList').add({
                    data: {
                        flag: false,
                        year: year,
                        mon: mon,
                        day: day,
                        newArr
                    }
                })
                .then(res => {
                    rvw_arr = []
                    newArr = {}
                    console.log('用户退出操作', newArr)
                })
        }
        this.stopAudio() // 音频停止播放

        // 更新用户表表
        await common.upUserData()
    },
})